/*
 * Wazuh Vulnerability Scanner - Unit Tests
 * Copyright (C) 2015, Wazuh Inc.
 * February 21, 2024.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#include "buildSingleAgentListContext_test.hpp"
#include "TrampolineOsDataCache.hpp"
#include "TrampolineSocketDBWrapper.hpp"
#include "buildSingleAgentListContext.hpp"

TEST_F(BuildSingleAgentListContextTest, BuildSingleAgentListContext)
{
    spSocketDBWrapperMock = std::make_shared<MockSocketDBWrapper>();
    EXPECT_CALL(*spSocketDBWrapperMock, query(testing::_, testing::_)).Times(1);

    const auto jsonData =
        R"({
        "agent_info": {
          "agent_id":"001"
        },
        "action":"upgradeAgentDB"})"_json;

    std::variant<const SyscollectorDeltas::Delta*, const SyscollectorSynchronization::SyncMsg*, const nlohmann::json*>
        data = &jsonData;

    auto singleAgentContext = std::make_shared<
        TBuildSingleAgentListInfoContext<TScanContext<TrampolineOsDataCache>, TrampolineSocketDBWrapper>>();

    auto scanContext = std::make_shared<TScanContext<TrampolineOsDataCache>>(data);
    singleAgentContext->handleRequest(scanContext);
}

TEST_F(BuildSingleAgentListContextTest, BuildSingleAgentListContextEmpty)
{
    spSocketDBWrapperMock = std::make_shared<MockSocketDBWrapper>();

    nlohmann::json queryResult = R"([])"_json;

    EXPECT_CALL(*spSocketDBWrapperMock, query(testing::_, testing::_))
        .Times(1)
        .WillOnce(testing::SetArgReferee<1>(queryResult));

    const auto jsonData =
        R"({
        "agent_info": {
          "agent_id":"001"
        },
        "action":"upgradeAgentDB"})"_json;

    std::variant<const SyscollectorDeltas::Delta*, const SyscollectorSynchronization::SyncMsg*, const nlohmann::json*>
        data = &jsonData;

    auto singleAgentContext = std::make_shared<
        TBuildSingleAgentListInfoContext<TScanContext<TrampolineOsDataCache>, TrampolineSocketDBWrapper>>();

    auto scanContext = std::make_shared<TScanContext<TrampolineOsDataCache>>(data);

    // Context is not used
    singleAgentContext->handleRequest(scanContext);

    EXPECT_EQ(scanContext->m_agents.size(), 0);
}

TEST_F(BuildSingleAgentListContextTest, BuildSingleAgentListContextWithElements)
{
    spSocketDBWrapperMock = std::make_shared<MockSocketDBWrapper>();
    const auto jsonData =
        R"({
        "agent_info": {
          "agent_id":"001"
        },
        "action":"upgradeAgentDB"})"_json;

    nlohmann::json queryResult = R"([{
        "id": 1,
        "name": "name",
        "version": "Wazuh v4.4.4",
        "ip": "192.168.0.1",
        "node_name": "node_1"
    }])"_json;

    EXPECT_CALL(*spSocketDBWrapperMock, query(testing::_, testing::_))
        .Times(1)
        .WillOnce(testing::SetArgReferee<1>(queryResult));

    std::variant<const SyscollectorDeltas::Delta*, const SyscollectorSynchronization::SyncMsg*, const nlohmann::json*>
        data = &jsonData;

    auto singleAgentContext = std::make_shared<
        TBuildSingleAgentListInfoContext<TScanContext<TrampolineOsDataCache>, TrampolineSocketDBWrapper>>();

    auto scanContext = std::make_shared<TScanContext<TrampolineOsDataCache>>(data);

    // Context is not used
    singleAgentContext->handleRequest(scanContext);

    EXPECT_EQ(scanContext->m_agents.size(), 1);

    auto agent = scanContext->m_agents[0];

    EXPECT_EQ(agent.id, "001");
    EXPECT_EQ(agent.name, "name");
    EXPECT_EQ(agent.version, "v4.4.4");
    EXPECT_EQ(agent.ip, "192.168.0.1");
}

TEST_F(BuildSingleAgentListContextTest, BuildSingleAgentListContextMultiple)
{
    spSocketDBWrapperMock = std::make_shared<MockSocketDBWrapper>();

    nlohmann::json queryResult = R"([{"element":"element1"},{"element":"element2"}])"_json;

    EXPECT_CALL(*spSocketDBWrapperMock, query(testing::_, testing::_))
        .Times(1)
        .WillOnce(testing::SetArgReferee<1>(queryResult));

    const auto jsonData =
        R"({
        "agent_info": {
          "agent_id":"001"
        },
        "action":"upgradeAgentDB"})"_json;

    std::variant<const SyscollectorDeltas::Delta*, const SyscollectorSynchronization::SyncMsg*, const nlohmann::json*>
        data = &jsonData;

    auto singleAgentContext = std::make_shared<
        TBuildSingleAgentListInfoContext<TScanContext<TrampolineOsDataCache>, TrampolineSocketDBWrapper>>();

    auto scanContext = std::make_shared<TScanContext<TrampolineOsDataCache>>(data);

    // Context is not used
    singleAgentContext->handleRequest(scanContext);

    EXPECT_EQ(scanContext->m_agents.size(), 0);
}

TEST_F(BuildSingleAgentListContextTest, ExceptionOnDB)
{
    spSocketDBWrapperMock = std::make_shared<MockSocketDBWrapper>();

    EXPECT_CALL(*spSocketDBWrapperMock, query(testing::_, testing::_))
        .Times(1)
        .WillOnce(testing::Throw(SocketDbWrapperException("Error on DB")));

    const auto jsonData = R"(
        {
            "agent_info": {
                "agent_id":"001"
            },
            "action":"upgradeAgentDB"
        })"_json;

    std::variant<const SyscollectorDeltas::Delta*, const SyscollectorSynchronization::SyncMsg*, const nlohmann::json*>
        data = &jsonData;

    auto singleAgentContext = std::make_shared<
        TBuildSingleAgentListInfoContext<TScanContext<TrampolineOsDataCache>, TrampolineSocketDBWrapper>>();

    auto scanContext = std::make_shared<TScanContext<TrampolineOsDataCache>>(data);

    // Context is not used
    EXPECT_THROW(singleAgentContext->handleRequest(scanContext), WdbDataException);

    spSocketDBWrapperMock.reset();
}
